import 'package:flutter/material.dart';
import 'dart:math';

enum DragState {
  back,
  normal,
}

class DetailPage extends StatefulWidget {
  String heroTag;
  DetailPage({@required this.heroTag, Key key}) : super(key: key);

  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  double offsetX = 0.0;
  double offsetY = 0.0;
  var dragState = DragState.normal;

  @override
  Widget build(BuildContext context) {
    return _body();
  }

  double _transformScale(double height) {
    return dragState == DragState.normal
        ? 1.0
        : min(1.0, 1 - 0.5 * offsetY.abs() / height);
  }

  Offset _translate() {
    return dragState == DragState.back
        ? Offset(offsetX, offsetY)
        : Offset(0, max(0, offsetY));
  }

  Widget _body() {
    final width = MediaQuery.of(context).size.width;
    final height = MediaQuery.of(context).size.height;

    return Transform.scale(
      scale: _transformScale(height),
      child: Transform.translate(
        offset: _translate(),
        child: Hero(
          tag: widget.heroTag,
          child: GestureDetector(
            onTap: () {},
            onPanDown: (_) {
              dragState = DragState.normal;
            },
            onPanStart: (_) {},
            onPanEnd: (_) {
              _gesturePanEnd(context, height);
            },
            onPanUpdate: (details) {
              _gesturePanUpdate(details, height);
            },
            child: Container(
              color: Colors.green,
            ),
          ),
        ),
      ),
    );
  }

  void _gesturePanEnd(BuildContext context, double height) {
    if (offsetY < -100) {
      Navigator.pop(context);
    } else if (offsetY < 0) {
      _restoreOriginal();
    } else if (dragState == DragState.back) {
      // Navigator.pop(context); // 下拉看是否需要关闭
      _restoreOriginal(); //下拉不用关闭则恢复原状
    } else if (offsetY >= 0) {
      _restoreOriginal();
    }
  }

  void _gesturePanUpdate(DragUpdateDetails details, double height) {
    if (dragState == DragState.normal) {
      dragState = DragState.back;
    }

    if (dragState == DragState.back) {
      offsetX += details.delta.dx;
    }

    offsetY += details.delta.dy;
    if (offsetY.abs() > height) {
      offsetY = -height * 0.6;
      offsetX = 0;
    } else {}

    _refreshUI();
  }

// 不符合退出逻辑则恢复原状
  void _restoreOriginal() {
    offsetX = 0;
    offsetY = 0;

    _refreshUI();
  }

  void _refreshUI() {
    setState(() {});
  }
}
